package com.tjbklx1.redis.chap04;

import java.lang.reflect.Method;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;

/**
 * 测试类,测试 pipeline 的效率,案例是UpdateToken
 * 
 * @author tjbklx1
 * @date 2018-12-5
 */
public class App43 {
	public static void main(String[] args) throws InterruptedException {
		Jedis conn = new Jedis("localhost");
		conn.select(0);
		new App43().testBenchmarkUpdateToken(conn);
	}

	private void testBenchmarkUpdateToken(Jedis conn) {
		System.out.println("\n----- testBenchmarkUpdate -----");
		benchmarkUpdateToken(conn, 5);
	}

	/**
	 * 利用反射的方式 批量执行 updateToken updateTokenPipeline 这两个方法,测试效率
	 * 
	 * @param conn
	 * @param duration
	 */
	public void benchmarkUpdateToken(Jedis conn, int duration) {
		try {
			@SuppressWarnings("rawtypes")
			Class[] args = new Class[] { Jedis.class, String.class, String.class, String.class };
			Method[] methods = new Method[] { this.getClass().getDeclaredMethod("updateToken", args), this.getClass().getDeclaredMethod("updateTokenPipeline", args), };
			for (Method method : methods) {
				int count = 0;
				long start = System.currentTimeMillis();
				long end = start + (duration * 1000);
				while (System.currentTimeMillis() < end) {
					count++;
					method.invoke(this, conn, "token", "user", "item");
				}
				long delta = System.currentTimeMillis() - start;
				System.out.println(method.getName() + ' ' + count + ' ' + (delta / 1000) + ' ' + (count / (delta / 1000)));
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 普通方式
	 * 
	 * @param conn
	 * @param token
	 * @param user
	 * @param item
	 */
	public void updateToken(Jedis conn, String token, String user, String item) {
		long timestamp = System.currentTimeMillis() / 1000;
		conn.hset("login:", token, user);
		conn.zadd("recent:", timestamp, token);
		if (item != null) {
			conn.zadd("viewed:" + token, timestamp, item);
			conn.zremrangeByRank("viewed:" + token, 0, -26);
			conn.zincrby("viewed:", -1, item);
		}
	}

	/**
	 * pipeline 方式
	 * 
	 * @param conn
	 * @param token
	 * @param user
	 * @param item
	 */
	public void updateTokenPipeline(Jedis conn, String token, String user, String item) {
		long timestamp = System.currentTimeMillis() / 1000;
		Pipeline pipe = conn.pipelined();
		pipe.multi();
		pipe.hset("login:", token, user);
		pipe.zadd("recent:", timestamp, token);
		if (item != null) {
			pipe.zadd("viewed:" + token, timestamp, item);
			pipe.zremrangeByRank("viewed:" + token, 0, -26);
			pipe.zincrby("viewed:", -1, item);
		}
		pipe.exec();
	}

}
